import { GameStorage } from "../../../../extensions/cocos-scaffold-3x/assets/GameStorage";
import { RandomPseudo } from "../../../../extensions/cocos-scaffold-3x/assets/common/RandomPseudo";
import { gg } from "../../../Game";
import { JCCfgDef } from "./JCCfgDef";
import { JCEventDef } from "./JCEventDef";

export class JokerStorage extends GameStorage {
    constructor() {
        super("Joker")
    }
    async initialize() {

    }
}




export namespace JC {

    /**花色 */
    export enum ECardSuit {
        Spade = 1, // 黑桃
        Heart = 2, // 红桃
        Diamond = 3, // 方块
        Club = 4, // 梅花
    }

    /**
     * 牌型
     */
    export enum EHandRank {
        HighCard = 1, // 高牌
        Pair = 2, // 一对
        TwoPair = 3, // 两对
        ThreeOfAKind = 4, // 三条
        Straight = 5, // 顺子
        Flush = 6, // 同花
        FullHouse = 7, // 葫芦
        FourOfAKind = 8, // 四条
        StraightFlush = 9, // 同花顺
        RoyalFlush = 10, // 皇家同花顺
        FiveOfAKind = 11, // 五条
        FullHouseFlush = 12,//同花葫芦
        FiveOfAKindFlush = 13, // 同花五条
    }


    /**
     * 牌型
     */
    export const EHandRankNameMap = {
        1: "高牌", // 高牌
        2: "一对", // 一对
        3: "两对", // 两对
        4: "三条", // 三条
        5: "顺子", // 顺子
        6: "同花", // 同花
        7: "葫芦", // 葫芦
        8: "四条", // 四条
        9: "同花顺", // 同花顺
        10: "皇家同花顺", // 皇家同花顺
        11: "五条", // 五条
        12: "同花葫芦",//同花葫芦
        13: "五条", // 同花五条
    }




    /**关卡状态 */
    export enum EPokerGameStageState {
        wait = 0,
        doing = 1,
        finished = 2
    }

    /**关卡 */
    export class PokerGameStage {
        constructor(
            public index: number,
            public targetNum: number,
            public base: number = 0,
            public mul: number = 0,
            public score: number = 0,
            public state: EPokerGameStageState = EPokerGameStageState.wait,
        ) { }

        addScore(score: number) {
            const oldScore = this.score
            this.score += score;
            console.log("addScore", oldScore, this.score);

            gg.eventTarget.emit(JCEventDef.stageAddScore, oldScore, this.score)
        }
    }

    export class PokerGame {
        /**牌堆*/
        pockerDeck: PokerCard[] = []

        fullDeckCardNum = 0

        /**小丑牌列表*/
        jokerCards: JokerCard[] = []

        /**手牌列表*/
        handPokerCards: PokerCard[] = []

        /**计算中的手牌列表*/
        playingPokerCards: PokerCard[] = []

        /**打完的手牌列表 */
        usedPokerCards: PokerCard[] = []

        /**关卡列表 */
        stageArr: PokerGameStage[] = []

        /**牌型等级列表 */
        handRanks: HandRank[] = []

        handPokerCardsLimit: number = 8

        playCardNumLimit = 5

        random: RandomPseudo

        leftPlayTimes = 4
        leftDropTimes = 3


        straightLimit = 5
        flushLimit = 5
        /**当前关卡 */
        get currentStage() {
            const stage = this.stageArr.find(stage => stage.state == EPokerGameStageState.wait)
            const preStage = this.stageArr[stage.index - 1]
            if (preStage && preStage.state == EPokerGameStageState.doing) {
                return preStage
            }

            return stage
        }

        /**开始关卡 */
        startNextStage() {
            if (this.currentStage.state == EPokerGameStageState.doing) {
                this.currentStage.state = EPokerGameStageState.finished
            }
            this.currentStage.state = EPokerGameStageState.doing
            this.playingPokerCards = []
            this.leftPlayTimes = 4
            this.leftDropTimes = 3

            while (this.usedPokerCards.length) {
                this.pockerDeck.push(this.usedPokerCards.pop())
            }

            while (this.handPokerCards.length) {
                this.pockerDeck.push(this.handPokerCards.pop())
            }
            this.handPokerCards = []

            this.pockerDeck = this.random.shuffle(this.pockerDeck)
            gg.eventTarget.emit(JCEventDef.startNewStage)
        }


        addNewCardToDeck(card: PokerCard) {
            this.pockerDeck.push(card)
            this.fullDeckCardNum++
        }
        /**开始新的一局 */
        makeNew() {
            this.random = new RandomPseudo(Date.now())
            this.pockerDeck = []
            this.jokerCards = []


            const carNumPerType = 52 / 4
            /**初始化关卡 */
            let stageScore = 300
            for (let index = 0; index < 24; index++) {
                this.stageArr.push(new PokerGameStage(index, stageScore))
                stageScore += 150
            }

            /**初始化牌库 */
            for (let i = 0; i < 4; i++) {
                for (let j = 0; j < carNumPerType; j++) {
                    const point = j == 0 ? 14 : j + 1
                    const value = j == 0 ? 11 : Math.min(10, j + 1)
                    this.addNewCardToDeck(new PokerCard(i * carNumPerType + j, i, point, value))
                }
            }

            /**初始化牌型列表 */
            const handRankCfg = gg.cfgArr(JCCfgDef.HandRank)
            for (let index = 0; index < handRankCfg.length; index++) {
                const cfg = handRankCfg[index];
                this.handRanks.push(new HandRank(1, cfg.id, cfg.base, cfg.mul, cfg))
            }
        }



        /**
         * 抽卡
         */
        drawCards() {
            const newCards = []
            while (this.handPokerCards.length < this.handPokerCardsLimit && this.pockerDeck.length) {
                const card = this.pockerDeck.pop()
                this.handPokerCards.push(card)
                newCards.push(card)
            }
            return newCards
        }

        playCards(cards: PokerCard[]) {
            this.leftPlayTimes--
            const rank = this.analyzePokerHand(cards)
            console.log(rank, EHandRankNameMap[rank.handRank]);


            this.playingPokerCards.length = 0
            cards.forEach(card => {
                this.handPokerCards.splice(this.handPokerCards.indexOf(card), 1)
                this.playingPokerCards.unshift(card)
            })
            return { rankType: rank.handRank, handRankCards: rank.handCards, handRank: this.handRanks.find(i => i.type == rank.handRank) }

        }

        dropCards(cards: PokerCard[]) {
            this.leftDropTimes--
            cards.forEach(card => {
                this.handPokerCards.splice(this.handPokerCards.indexOf(card), 1)
                this.usedPokerCards.unshift(card)
            })


        }










        // 卡牌列表中最长的顺子
        maxStraight(cards: PokerCard[]) {

            const sortedCardsByPoint = cards.slice().sort((a, b) => a.point - b.point);
            /**去掉重复的牌 */
            for (let i = 1; i < sortedCardsByPoint.length;) {
                const card = sortedCardsByPoint[i]
                if (card.point == sortedCardsByPoint[i - 1].point) {
                    sortedCardsByPoint.splice(i, 1)
                } else {
                    i++
                }
            }

            let currentStraght = [sortedCardsByPoint[0]]
            let straghtArr = [currentStraght]


            for (let i = 0; i < sortedCardsByPoint.length - 1; i++) {
                const card = sortedCardsByPoint[i]
                const nextCard = sortedCardsByPoint[i + 1]
                if (nextCard.point - card.point !== 1 &&
                    // 处理A可以作为1的情况
                    !(sortedCardsByPoint[0].point === 2 && nextCard.point === 14)) {
                    currentStraght = [nextCard]
                    straghtArr.push(currentStraght)
                    continue
                }
                currentStraght.push(nextCard)
            }

            straghtArr.sort((a, b) => {
                return b.length - a.length
            })
            return straghtArr[0]
        }

        // 卡牌列表中最长的相同牌
        maxOneKind(cards: PokerCard[]) {

            const sortedCardsByPoint = cards.slice().sort((a, b) => a.point - b.point);


            let currentOneKind = [sortedCardsByPoint[0]]
            let oneKindArr = [currentOneKind]


            for (let i = 0; i < sortedCardsByPoint.length - 1; i++) {
                const card = sortedCardsByPoint[i]
                const nextCard = sortedCardsByPoint[i + 1]
                if (nextCard.point != card.point) {
                    currentOneKind = [nextCard]
                    oneKindArr.push(currentOneKind)
                    continue
                }
                currentOneKind.push(nextCard)
            }

            oneKindArr.sort((a, b) => {
                return b.length - a.length
            })
            return oneKindArr[0]
        }



        /**卡牌列表中suit最多的卡牌的子列表 */
        getSuitMostCards(cards: PokerCard[]) {
            let suitCounts = new Map<number, number>();
            let maxCount = 0
            let maxCountSuit = 0
            for (let i = 0; i < cards.length; i++) {
                let card = cards[i];
                let suit = card.suit;
                let count = suitCounts.get(suit) || 0;
                if (count > maxCount) {
                    maxCount = count
                    maxCountSuit = suit
                }
                suitCounts.set(suit, count + 1);
            }
            return cards.filter(i => i.suit == maxCountSuit)
        }




        // 最长的同花
        maxFlush(cards: PokerCard[]) {
            const cardGroupArr: { suit: ECardSuit, cards: PokerCard[] }[] = []

            for (let index = 0; index < cards.length; index++) {
                const card = cards[index];
                let cardGroup = cardGroupArr.find(i => i.suit == card.suit)
                if (!cardGroup) {
                    cardGroup = { suit: card.suit, cards: [] }
                    cardGroupArr.push(cardGroup)
                }
                cardGroup.cards.push(card)

            }
            cardGroupArr.sort(((a, b) => b.cards.length - a.cards.length))

            return cardGroupArr[0].cards
        }

        orgionCardsBySoredCards(cards: PokerCard[], sortedCards: PokerCard[]): PokerCard[] {
            return cards.filter(i => sortedCards.find(card => card.id == i.id))
        }
        // 创建一个主函数，用于判断并返回德州扑克的牌型和满足牌型的牌
        analyzePokerHand(cards: PokerCard[]): { handRank: EHandRank, handCards: PokerCard[] } {
            // 先按点数排序
            const sortedCardsByPoint = cards.slice().sort((a, b) => b.point - a.point);
            const pointSet = new Set(sortedCardsByPoint.map(card => card.point));
            const maxStraight = this.maxStraight(cards)
            const maxOneKind = this.maxOneKind(cards)

            const maxFlush = this.maxFlush(cards)
            // 检查特殊牌型：皇家同花顺
            if (maxStraight.length >= this.straightLimit && maxFlush.length >= this.flushLimit && sortedCardsByPoint[0].point === 14 && sortedCardsByPoint[4].point >= 10) {
                return { handRank: EHandRank.RoyalFlush, handCards: maxStraight };
            }

            if (sortedCardsByPoint.length >= 5 && maxOneKind.length >= 5) { // 五条
                return { handRank: EHandRank.FiveOfAKind, handCards: cards };
            }
            // 检查特殊牌型：同花葫芦
            if (sortedCardsByPoint.length >= 5 && maxFlush.length >= this.flushLimit && pointSet.size === sortedCardsByPoint.length - 3) {
                return { handRank: EHandRank.FullHouseFlush, handCards: cards };
            }

            // 检查常规牌型：同花顺
            if (maxStraight.length >= this.straightLimit && maxFlush.length >= this.flushLimit) {
                return { handRank: EHandRank.StraightFlush, handCards: maxStraight };
            }

            // 检查其他牌型，依次降低优先级
            if (sortedCardsByPoint.length >= 4 && maxOneKind.length >= 4) { // 四条
                return { handRank: EHandRank.FourOfAKind, handCards: maxOneKind };
            }
            if (sortedCardsByPoint.length >= 5 && pointSet.size === sortedCardsByPoint.length - 3) { // 葫芦
                return { handRank: EHandRank.FullHouse, handCards: cards };
            }
            if (maxFlush.length >= this.flushLimit) { // 同花
                return { handRank: EHandRank.Flush, handCards: this.getSuitMostCards(cards) };
            }
            if (maxStraight.length >= this.straightLimit) { // 顺子
                return { handRank: EHandRank.Straight, handCards: maxStraight };
            }
            if (sortedCardsByPoint.length >= 4 && pointSet.size === sortedCardsByPoint.length - 2) { // 两对
                let pairs: PokerCard[][] = [];
                for (let i = 0; i < sortedCardsByPoint.length - 1; i++) {
                    if (sortedCardsByPoint[i].point === sortedCardsByPoint[i + 1].point) {
                        pairs.push([sortedCardsByPoint[i], sortedCardsByPoint[i + 1]]);
                        i++;
                    }
                }
                if (pairs.length === 2) {
                    return { handRank: EHandRank.TwoPair, handCards: this.orgionCardsBySoredCards(cards, [...pairs[0], ...pairs[1]]) };
                }
            }
            if (sortedCardsByPoint.length >= 3 && maxOneKind.length >= 3) { // 三条
                return { handRank: EHandRank.ThreeOfAKind, handCards: this.orgionCardsBySoredCards(cards, maxOneKind) };
            }
            if (sortedCardsByPoint.length >= 2 && pointSet.size === cards.length - 1) { // 一对
                let pairs: PokerCard[] = [];
                for (let i = 0; i < sortedCardsByPoint.length - 1; i++) {
                    if (sortedCardsByPoint[i].point === sortedCardsByPoint[i + 1].point) {
                        pairs = [sortedCardsByPoint[i], sortedCardsByPoint[i + 1]];
                        break;
                    }
                }
                if (pairs.length === 2) {
                    return { handRank: EHandRank.Pair, handCards: this.orgionCardsBySoredCards(cards, pairs) };
                }
            }

            // 如果没有匹配任何牌型，则为高牌
            return { handRank: EHandRank.HighCard, handCards: [sortedCardsByPoint[0]] };
        }
    }

    export class HandRank {

        constructor(
            public level: number,
            public type: EHandRank,
            public base: number,
            public mul: number,
            public cfg: JCCfgDef.HandRank
        ) {


        }

        getBase() {
            return this.base + this.cfg.basePerLevel * (this.level -1)
        }

        getMul() {
            return this.mul + this.cfg.mulPerLevel * (this.level - 1)
        } ƒ








    }

    export class ShopItem {

    }

    export class PokerShop {

    }


    export class PokerCard {
        constructor(
            /**唯一id */
            public id: number,
            /**花色 */
            public suit: ECardSuit,
            /**点数 */
            public point: number,
            /**价值 */
            public value: number
        ) { }
    }

    export class JokerCard {
        constructor(public id: number, public name: string) { }
    }

    export class ConsumeCard {
        constructor(public id: number, public name: string) { }
    }







}
